﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using Common.Utilities;
using Common.Utilities.Dispatcher;
using Workflows.Components.ETL.Properties;

namespace Workflows.Components.ETL
{
    /// <summary>
    /// 
    /// </summary>
    [Serializable]
    public class OracleBulkLoadComponent:WorkflowComponentBase
    {
        #region members
        private OracleBulkLoadInstruction _Instruction;
        private OracleBulkLoadOutput _Output;

        public override InstructionBase Instruction
        {
            get { return _Instruction; }
            set { _Instruction = (OracleBulkLoadInstruction) value; }
        }

        public override ResultBase Output
        {
            get { return _Output; }
            set { _Output = (OracleBulkLoadOutput)value; }
        }

        /// <summary></summary>
        public string SqlLoaderProgramFilePath
        {
            get
            {
                return this._Instruction.SqlLoaderProgramFilePath;
            }
            set
            {
                this._Instruction.SqlLoaderProgramFilePath = value;
            }
        }

        /// <summary></summary>
        public string ConnectionString
        {
            get
            {
                return this._Instruction.ConnectionString;
            }
            set
            {
                this._Instruction.ConnectionString = value;
            }
        }

        /// <summary></summary>
        public string TableName
        {
            get
            {
                return this._Instruction.TableName;
            }
            set
            {
                this._Instruction.TableName = value;
            }
        }

        /// <summary></summary>
        public string SrcDataFilePath
        {
            get
            {
                return this._Instruction.SrcDataFilePath;
            }
            set
            {
                this._Instruction.SrcDataFilePath = value;
            }
        }

        /// <summary></summary>
        public FieldDelimiter FieldDelimiter
        {
            get
            {
                return this._Instruction.FieldDelimiter;
            }
            set
            {
                this._Instruction.FieldDelimiter = value;
            }
        }

        /// <summary></summary>
        public Dictionary<string, int> FieldSizes
        {
            get
            {
                return this._Instruction.FieldSizes;
            }
            set
            {
                this._Instruction.FieldSizes = value;
            }
        }

        /// <summary></summary>
        public List<string> TableFields
        {
            get
            {
                return this._Instruction.TableFields;
            }
            set
            {
                this._Instruction.TableFields = value;
            }
        }

        /// <summary></summary>
        public string SrcConnStr
        {
            get
            {
                return this._Instruction.SrcConnStr;
            }
            set
            {
                this._Instruction.SrcConnStr = value;
            }
        }

        /// <summary></summary>
        public string SelectSqlStatement
        {
            get
            {
                return this._Instruction.SelectSqlStatement;
            }
            set
            {
                this._Instruction.SelectSqlStatement = value;
            }
        }

        /// <summary></summary>
        public bool TruncateTableBeforeInsert
        {
            get
            {
                return this._Instruction.TruncateTableBeforeInsert;
            }
            set
            {
                this._Instruction.TruncateTableBeforeInsert = value;
            }
        }
        #endregion

        /// <summary></summary>
        public OracleBulkLoadComponent():base()
        {
            this.ComponentName = "Oracle bulk load";
            this.Description = "Bulk load data to oracle table using sqlldr utility";
            this.ComponentIcon = Resources.dataprovider;
            this.ComponentImage = Resources.fd;
            this.ComponentActivityType = WorkflowActivityType.SimpleActivity;
            this.ComponentCategory = WorkflowComponentCategory.ETL.ToString();

            this._Instruction =
                new OracleBulkLoadInstruction(this.ComponentID, Guid.Empty, string.Empty, string.Empty, string.Empty,
                                              string.Empty, ETL.FieldDelimiter.Tab, null, null,
                                              string.Empty, string.Empty, false);
            this._Output = new OracleBulkLoadOutput(this.ComponentID, Guid.Empty, 0, 0, string.Empty, string.Empty);
        }

        /// <summary></summary>
        public override XmlNode Serialize(ref XmlDocument xDoc, ref XmlNode parentNode)
        {
            XmlNode xNode = base.Serialize(ref xDoc, ref parentNode);

            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SqlldrFilePath", this.SqlLoaderProgramFilePath);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ConnectionString", this.ConnectionString);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TableName", this.TableName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SrcDataFilePath", this.SrcDataFilePath);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "FieldDelimiter", ((int)this.FieldDelimiter).ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SrcConnStr", this.SrcConnStr);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SelectSqlStatement", this.SelectSqlStatement);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TrucateTargetTableBeforeLoad", this.TruncateTableBeforeInsert.ToString());

            if (this.FieldSizes != null && this.FieldSizes.Count > 0)
            {
                XmlNode fieldSizeRootNode = XmlDataUtil.AddElement(ref xDoc, xNode, "FieldSizes");
                foreach (string fieldName in this.FieldSizes.Keys)
                {
                    XmlNode fieldSizeNode = XmlDataUtil.AddElement(ref xDoc, fieldSizeRootNode, "FieldSize");
                    XmlDataUtil.UpdateAttribute(ref xDoc, fieldSizeNode, "FieldName", fieldName);
                    XmlDataUtil.UpdateAttribute(ref xDoc, fieldSizeNode, "FieldSize", this.FieldSizes[fieldName].ToString());
                }
            }
            if (this.TableFields != null && this.TableFields.Count > 0)
            {
                XmlNode fieldRootNode = XmlDataUtil.AddElement(ref xDoc, xNode, "Fields");
                foreach (string fieldName in this.TableFields)
                {
                    XmlNode fieldNode = XmlDataUtil.AddElement(ref xDoc, fieldRootNode, "Field");
                    XmlDataUtil.UpdateAttribute(ref xDoc, fieldNode, "FieldName", fieldName);
                }
            }
            return xNode;
        }

        /// <summary></summary>
        public override WorkflowComponentBase Instantiate(XmlNode xNode)
        {
            if (xNode.Attributes.GetNamedItem("Type").Value == this.GetType().FullName)
            {
                OracleBulkLoadComponent wfComponent = base.Instantiate(xNode) as OracleBulkLoadComponent;

                wfComponent.SqlLoaderProgramFilePath = xNode.Attributes.GetNamedItem("SqlldrFilePath").Value;
                wfComponent.ConnectionString = xNode.Attributes.GetNamedItem("ConnectionString").Value;
                wfComponent.TableName = xNode.Attributes.GetNamedItem("TableName").Value;
                wfComponent.SrcDataFilePath = xNode.Attributes.GetNamedItem("SrcDataFilePath").Value;
                wfComponent.FieldDelimiter =
                    (FieldDelimiter)int.Parse(xNode.Attributes.GetNamedItem("FieldDelimiter").Value);
                wfComponent.SrcConnStr = XmlDataUtil.GetAttributeValue(xNode, "SrcConnStr", "");
                wfComponent.SelectSqlStatement = XmlDataUtil.GetAttributeValue(xNode, "SelectSqlStatement", "");
                wfComponent.TruncateTableBeforeInsert = bool.Parse(XmlDataUtil.GetAttributeValue(xNode, "TruncateTargateTableBeforeLoad", false.ToString()));

                wfComponent.FieldSizes = null;
                XmlNodeList fieldSizeNodes = xNode.SelectNodes("FieldSizes/FieldSize");
                if (fieldSizeNodes != null && fieldSizeNodes.Count > 0)
                {
                    wfComponent.FieldSizes = new Dictionary<string, int>();
                    foreach (XmlNode fieldSizeNode in fieldSizeNodes)
                    {
                        string fieldName = fieldSizeNode.Attributes.GetNamedItem("FieldName").Value;
                        int fieldSize = int.Parse(fieldSizeNode.Attributes.GetNamedItem("FieldSize").Value);
                        wfComponent.FieldSizes.Add(fieldName, fieldSize);
                    }
                }
                XmlNodeList fieldNodes = xNode.SelectNodes("Fields/Field");
                wfComponent.TableFields = null;
                if (fieldNodes != null && fieldNodes.Count > 0)
                {
                    wfComponent.TableFields = new List<string>();
                    foreach (XmlNode fieldNode in fieldNodes)
                    {
                        wfComponent.TableFields.Add(fieldNode.Attributes.GetNamedItem("FieldName").Value);
                    }
                }

                return wfComponent;
            }
            else
            {
                throw new Exception("Unable to instantiate component: invalid type specified in xml node");
            }
        }
    }
}
